package com.spring;


import com.spring.AOP.AopInterface.ProxyFactory;
import com.spring.AOP.DefaultProxyFactory;
import com.spring.Transaction.EnableTransaction;
import com.spring.Transaction.EnableTransactionManagement;
import com.spring.springAnnotation.EnableAspectJAutoProxy;
import com.spring.springInterface.BeanDefinition;
import com.spring.springInterface.BeanPostProcessor;
import com.spring.springInterface.Context;
import com.spring.springInterface.DisposableBean;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.spring.ConfigReader.getPath;

public class LaiYaoApplicationContext implements Context {
    //1.创建BeanFactory
    private final DefaultBeanFactory beanFactory;
    private final BeanDefinitionScanner beanDefinitionScanner;
    private final DefaultBeanDefinitionRegistry registry=new DefaultBeanDefinitionRegistry();
    public LaiYaoApplicationContext(Class configClass) throws Exception {
        //如果配置类上有@EnableAspectJAutoProxy注解就开启aop
        boolean needAop = configClass.isAnnotationPresent(EnableAspectJAutoProxy.class);
        this.beanFactory = needAop ? new DefaultBeanFactory(registry) : new DefaultBeanFactory();
        boolean needTransaction = configClass.isAnnotationPresent(EnableTransaction.class);
        //1.1初始化BeanFactory
        this.beanDefinitionScanner = new BeanDefinitionScanner(beanFactory);
        if(needAop) {
            DefaultProxyFactory defaultProxyFactory = (DefaultProxyFactory) beanFactory.getProxyFactory();
            defaultProxyFactory.register();
        }
        refresh(configClass);
    }
    @Override
    public void refresh(Class configClass) throws Exception {
        //TODO:准备刷新
        //TODO：执行BeanFactory后置处理器
        //2.进行扫描
       beanDefinitionScanner.scan(getPath(configClass));
       //填充registerBeanPostProcessors(beanFactory)
        registerBeanPostProcessors(beanFactory);
        //初始化单例bean
        beanFactory.initializeSingletonBean();
    }
    private void registerBeanPostProcessors(DefaultBeanFactory beanFactory) throws Exception {
        //1.获取所有BeanPostDefinition
        Map<String, BeanDefinition> beanDefinitionMap = beanFactory.getBeanDefinitionMap();
        List<String> postProcessorNames = new ArrayList<>();
        //2.遍历,获取BeanName
        for (String beanName : beanDefinitionMap.keySet()) {
            BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
            if (BeanPostProcessor.class.isAssignableFrom(beanDefinition.getBeanClass())) {
                DefaultProxyFactory proxyFactory = (DefaultProxyFactory) beanFactory.getProxyFactory();
                //实例化
                BeanPostProcessor beanPostProcessor = (BeanPostProcessor) beanDefinition.getBeanClass().newInstance();
                beanPostProcessor.setProxyCreator(proxyFactory);
                beanFactory.addBeanPostProcessor(beanPostProcessor);
                //放进单例池
                beanFactory.getSingletonObjects().put(beanName, beanPostProcessor);
            }
        }
        }
    //销毁方法
    public void close() throws Exception {
        // 调用BeanFactory的销毁方法，触发所有Bean的销毁
        beanFactory.destroySingletons();
        System.out.println("容器已完全关闭");
    }



    @Override
    public Object getBean(String name) throws Exception {
        return beanFactory.getBean(name);
    }

    @Override
    public <T> T getBean(Class<T> requiredType) throws Exception {
        return (T) beanFactory.getBean(requiredType);
    }

    @Override
    public boolean containsBean(String name) {
        return beanFactory.containsBean(name);
    }

    @Override
    public boolean isSingleton(String name) {
        return beanFactory.isSingleton(name);
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor processor) {
        beanFactory.addBeanPostProcessor(processor);
    }

    @Override
    public Object createBean(String beanName, DefaultBeanDefinition beanDefinition) throws Exception {
        return beanFactory.createBean(beanName, beanDefinition);
    }

    @Override
    public void initializeSingletonBean() {
        beanFactory.initializeSingletonBean();
    }

    @Override
    public HashMap<Class<?>, List<String>> getTypeMap() {
       return beanFactory.getTypeMap();
    }
}




